// Copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"context"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"time"

	"github.com/gorilla/websocket"
	"github.com/sirupsen/logrus"
	"inspur.com/cloudware/util"
	"inspur.com/cloudware/wscomm"
	"inspur.com/cloudware/wscomm/wsserver"
)

var addr = flag.String("addr", "127.0.0.1:3000", "websocket service address")

func main() {
	flag.Parse()
	logrus.SetReportCaller(true)
	ctx := context.Background()
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt)

	u := url.URL{Scheme: "ws", Host: *addr, Path: "/ws/v1/connect"}

	logrus.Printf("connecting to %s", u.String())
	for {
		err := run(ctx, u.String())
		if err != nil {
			logrus.Error(err)
		}
		time.Sleep(5 * time.Second)
	}

}

func run(ctx context.Context, url string) error {
	header := http.Header{}
	header.Add(wsserver.AgentIDHeader, "111111")
	//要求在握手请求中添加固定header   value为能代表这个host的id
	c, _, err := websocket.DefaultDialer.Dial(url, header)
	if err != nil {
		logrus.Error("dial error:", err)
		return err
	}
	defer c.Close()
	//建立连接后注册自己
	err = DoRegister(c)
	if err != nil {
		logrus.Error("DoRegister error: ", err)
		return err
	}
	done := make(chan struct{})

	//异步5s一次心跳
	go func() {
		ticker := time.NewTicker(time.Second * 5)
		defer ticker.Stop()

		for {
			select {
			case <-done:
				return
			case <-ticker.C:
				err := c.WriteControl(websocket.PingMessage, []byte("ping you"), time.Now().Add(time.Second*5))
				if err != nil {
					logrus.Println("write:", err)
					return
				}
			}
		}
	}()
	//同步读消息

	defer close(done)
	for {
		message_type, message, err := c.ReadMessage()
		if err != nil {
			logrus.Println("read:", err)
			return err
		}
		logrus.Printf("recv: %s", message)
		if message_type != websocket.TextMessage {
			return errors.New("server端报文类型异常")
		}
		var server_message wscomm.Message
		err = json.Unmarshal(message, &server_message)
		if err != nil {
			logrus.Println("收到server端报文，解析异常")
			// return err
		}
		//业务逻辑放这里
		DoAction(&server_message)
	}

}

func DoRegister(conn *websocket.Conn) error {
	// 连接成功后，获取节点信息  上报注册报文
	pwd, _ := os.Getwd()
	agentid := "sheldon_server1"
	host := &wscomm.RegHost{
		HostID:   "sheldon_server1",
		Sn:       "Inspur123456a!",
		HostName: pwd,
		BmcIp:    "192.168.93.132",
	}
	payloadByte, _ := json.Marshal(host)
	msid := util.GetRandomString(32)
	regmessage := &wscomm.Message{
		AgentID:     agentid,
		MessageID:   msid,
		Data:        payloadByte,
		MessageType: wscomm.Connect,
	}
	regmessageByte, _ := json.Marshal(regmessage)
	err := conn.WriteMessage(websocket.TextMessage, regmessageByte)
	if err != nil {
		logrus.Println("上报节点注册信息失败")
		return err
	}
	//等待服务端返回允许注册
	message_type, message, err := conn.ReadMessage()
	logrus.Println("reg  conn.ReadMessage")
	logrus.Println(string(message))
	if err == nil {
		if message_type != websocket.TextMessage {
			return errors.New("注册节点返回报文格式异常")
		}
		var server_message wscomm.Message
		err = json.Unmarshal(message, &server_message)
		if err != nil {
			logrus.Println("注册节点返回报文解析异常")
			return err
		}
		if server_message.MessageType == wscomm.Connect {
			logrus.Println("收到允许注册的报文")
		}

	} else {
		logrus.Println("读取消息失败")
		return err
	}

	return nil
}

//在这里增加收到message后的业务逻辑
func DoAction(msg *wscomm.Message) error {
	pwd, _ := os.Getwd()
	logrus.Printf("pwd===%s", pwd)
	//data内是具体业务数据
	str2 := string(msg.Data)
	fmt.Println(str2)
	return nil
}
